﻿using System;
using System.Collections.Generic;
using System.Linq;
using Yamfinder.Data;

namespace Yamfinder.Service
{
    public class ImportService : IImportService
    {
        private readonly IImportRepository _importRepository;
        private readonly ILexicalRepository _lexicalRepository;
        private readonly IDataDictonaryRepository _dataDictonaryRepository;

        public ImportService(IImportRepository importRepository, ILexicalRepository lexicalRepository, IDataDictonaryRepository dataDictonaryRepository)
        {
            _importRepository = importRepository;
            _lexicalRepository = lexicalRepository;
            _dataDictonaryRepository = dataDictonaryRepository;
        }

        public Guid StoreImportData(Dictionary<string, List<string>> data)
        {
            var table = new TempImportTable() {Data = data, DateAdded = DateTime.Now, Identifer = Guid.NewGuid()};
            _importRepository.Insert(table);
            return table.Identifer;
        }

        public IList<AnalysedImportColumn> GetAnalysedColumns(Guid id)
        {
            var table = _importRepository.Get(id);

            if (table == null)
                throw new ArgumentException("No such table in database.","id");

            var returnList = new List<AnalysedImportColumn>();
            var headers = table.Data.Keys.Select(x => x).ToList();

            foreach (var header in headers)
            {
                var column = new AnalysedImportColumn() {Name = header};

                int gpsCount = 0;
                int dateCount = 0;
                int intCount = 0; 
                int doubleCount = 0;
                int blankCount = 0;
                


                foreach (var value in table.Data[header])
                {
                    //GPS
                    var gpsSplit = value.Split(',');
                    if (gpsSplit.Count() == 2)
                    {
                        //Could be, check if numbers can be parsed
                        double lat;
                        if (double.TryParse(gpsSplit[0],out lat))
                        {
                            double lon;
                            if (double.TryParse(gpsSplit[1], out lon))
                            {
                                gpsCount++;
                            }
                        }
                    }

                    //Date
                    DateTime date;
                    if (DateTime.TryParse(value, out date))
                    {
                        dateCount++;
                    }
                    
                    //Int
                    int intValue;
                    if (int.TryParse(value, out intValue))
                    {
                        intCount++;
                    }

                    //Double
                    double doubleValue;
                    if (double.TryParse(value, out doubleValue))
                    {
                        doubleCount++;
                    }

                    //Blank could be any of the above
                    if (string.IsNullOrEmpty(value))
                    {
                        blankCount++;
                        doubleCount++;
                        intCount++;
                        dateCount++;
                        gpsCount++;
                    }
                }

                //Figure out which too use
                var totalRows = table.Data[header].Count;

                if (blankCount == totalRows)
                {
                    //If all fields are blank we shall assume TEXT
                    column.Type = DataType.Text;
                }
                else
                {
                    if (gpsCount == totalRows)
                    {
                        column.Type = DataType.GPSLocation;
                    }
                    else
                    {
                        if (dateCount == totalRows)
                        {
                            column.Type = DataType.Date;
                        }
                        else
                        {
                            if (intCount == totalRows)
                            {
                                column.Type = DataType.Integer;
                            }
                            else
                            {
                                column.Type = doubleCount == totalRows ? DataType.Decimal : DataType.Text;
                            }
                        }
                    }
                }

                returnList.Add(column);
            }

            return returnList;
        }

        public int SaveUsingMappings(Guid id, IList<ImportMapping> mappings)
        {
            //Find and add new fields to the data dictonary
            foreach (var importMapping in mappings)
            {
                var results = _dataDictonaryRepository.Query()
                    .Where(x => x.Name == importMapping.DatabaseName).Count();

                if (results <= 0)
                {
                    //Need to add new
                    _dataDictonaryRepository.Insert(new DataDictonaryEntry
                                                        {
                                                            IsDisplayed = false,
                                                            IsRequired = false,
                                                            Name = importMapping.DatabaseName,
                                                            Type = importMapping.Type
                                                        });
                }
            }

            //Get the data and start adding via the lexical repo
            var table = _importRepository.Get(id);

            var total = table.Data[table.Data.Keys.First()].Count;
            var lexicalEntries = new List<LexicalEntry>();

            for (int i = 0; i < total; i++)
            {
                var lexicalEntry = new LexicalEntry();

                foreach (var key in table.Data.Keys)
                {
                    var value = table.Data[key][i];

                    lexicalEntry.Fields.Add(key, value);
                }

                lexicalEntries.Add(lexicalEntry);
            }

            //Get count and commit
            var count = 0;
            foreach (var lexicalEntry in lexicalEntries)
            {
                _lexicalRepository.Insert(lexicalEntry);
                count++;
            }

            //Remove temp table
            _importRepository.Remove(id);

            return count;
        }
    }
}